import 'dart:convert';

import 'package:im_app/im/util/MapUtil.dart';
import 'package:logger/logger.dart';
import 'package:sqflite/sqflite.dart';

import '../pojo/ImPojo.dart';
import '../util/DateUtil.dart';
import '../util/ImSingleton.dart';
import 'BaseDao.dart';

class ImCollectDao extends BaseDao {

  final _logger = Logger(printer: PrettyPrinter(),);

  Future<ImCollect?> getByKey(String userId, String sessionId, String messageId) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    List? list = await database?.rawQuery("select * from im_collect where userId = ? and sessionId = ? and "
        "messageId = ?  limit 1",
        [userId, sessionId, messageId]);
    if (list != null && list.length > 0) {
      return Future.value(_toImCollect(list[0]));
    }
    return Future.value(null);
  }

  Future<List<ImCollect>> getCollects(String userId, String? search, List<ImMessageType>? messageTypes, int pageSize) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    String where = '';
    List<Object> args = [userId];
    if (search != null && search != '') {
      where += " and content like ? ";
      args.add('%${search}%');
    }
    if (messageTypes != null && messageTypes.isNotEmpty) {
      where += ' and messageType in (${messageTypes.map((mt)=>"?").join(",")})';
      args.addAll(messageTypes.map((mt)=>mt.name));
    }
    String sql = "select * from im_collect where status = 1 and userId = ? $where limit 0, $pageSize";
    List<Map<String, dynamic?>>? list = await database?.rawQuery(sql, args);
    return list != null ? Future.value(list.map((map)=>_toImCollect(map)).toList()) : Future.value([]);
  }

  Future<List<ImCollect>> getAll() async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    String sql = "select * from im_collect where status = 1";
    List<Map<String, dynamic?>>? list = await database?.rawQuery(sql);
    return list != null ? Future.value(list.map((map)=>_toImCollect(map)).toList()) : Future.value([]);
  }

  Future<void> batchInserts(List<ImCollect> imCollects) async {
    if (imCollects.isEmpty) return;
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    for (var imCollect in imCollects) {
      var data = _toInsertValueMap(imCollect);
      int? id = await database?.insert("im_collect", data);
      imCollect.id = id;
    }
  }

  Future<void> delete(ImCollect imCollect) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    int? size = await database?.delete("im_collect", where: "id=?", whereArgs: [imCollect.id!]);
    assert(size == 1);
  }

  Future<void> batchUpdates(List<ImCollect> imConfigs) async {
    if (imConfigs.isEmpty) return;
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    Batch? batch = database?.batch();
    for (var imConfig in imConfigs) {
      var data = _toUpdateValueMap(imConfig);
      batch?.update("im_collect", data, where: "id = ?", whereArgs:[imConfig.id]);
    }
    List<Object?>? list = await batch?.commit();
    _logger.i("batch json: " + jsonEncode(list));
  }

  Map<String, dynamic?> _toUpdateValueMap(ImCollect imCollect) {
    Map<String, dynamic?> map = {};
    map['content'] = imCollect.content;
    map["status"]= imCollect.status?.value;
    map["serverId"]= imCollect.serverId;
    map["labelIds"]= imCollect.labelIds;
    map['updateTime'] = DateUtil.formatDate(imCollect.updateTime);
    return map;
  }

  Map<String, dynamic?> _toInsertValueMap(ImCollect imCollect) {
    Map<String, dynamic?> map = {};
    map['userId'] = imCollect.userId;
    map['messageId'] = imCollect.messageId;
    map['sessionId'] = imCollect.sessionId;
    map['content'] = imCollect.content;
    map["status"]= imCollect.status?.value;
    map["messageType"]= imCollect.messageType.name;
    map["serverId"]= imCollect.serverId;
    map["labelIds"]= imCollect.labelIds;
    map['createTime'] = DateUtil.formatDate(imCollect.createTime);
    map['updateTime'] = DateUtil.formatDate(imCollect.updateTime);
    return map;
  }

  ImCollect _toImCollect(Map<String, dynamic> map) {
    var collect = ImCollect(userId: MapUtil.getString(map, "userId"),
        content: MapUtil.getString(map, "content"),
        messageId: MapUtil.getString(map, "messageId"),
        sessionId: MapUtil.getString(map, "sessionId"),
        status: ImCollectStatus.ofValue(MapUtil.getInt(map, "status")),
        messageType: ImMessageType.ofName(MapUtil.getString(map, "messageType")),
    );
    collect.id = MapUtil.getInt(map, "id");
    collect.serverId = MapUtil.getStringOrNull(map, "serverId");
    collect.labelIds = MapUtil.getStringOrNull(map, "labelIds");
    collect.createTime = MapUtil.getDate(map, "createTime");
    collect.updateTime = MapUtil.getDate(map, "updateTime");
    return collect;
  }
}